import fs from 'fs';
import scope from './scope';
import script from './script';
import func from './func';
const Scope = scope;
const Script = script;
const useType = {
	include: Symbol(),
	echo: Symbol(),
	text: Symbol(),
}
const useTypeSet = new Set([useType.include, useType.echo, useType.text]);

const symbol = {
	CONTINUE: Symbol(), 
	BREAK: Symbol(), 
};
const next = _=> next;
let nameRegExp = /^[a-zA-Z0-9_\-\~\!\@\#\$\*]+$/;

/**
 * 模板类
 * 
 * @attribute	{String}	filename	文件名
 * @readOnly	{String}	status		状态
 * @readOnly	{Object}	functmpl	原生的functmpl获取函数
 * @readOnly	{Object}	useType		可用类型
 * @readOnly	{Object}	symbol		符号猎豹
 * @readOnly	{Object}	scope		作用域类
 * @readOnly	{Object}	script		脚本类
 * 
 * @function	@async	setTemplate(text)					设置模板
 * @function	@async	loadFile(filename)					加载模板文件
 * @function			use(func, funcType)					添加处理函数
 * @function	@async	parse(...param)						解析数据到模板
 * @function	@async	parseList(list, scope)				解析列表
 * @function	@async	parseNode(node, scope)				解析节点
 * @function	@async	repeat(list, scope, data, options)	将列表重复执行
 * 
 * @attribute	{String}	_status		状态
 * @attribute	{String}	_filename	文件名
 * @attribute	{String}	_template	
 * @attribute	{String}	_path		
 * @attribute	{Functmpl}	_parent		
 * @attribute	{Array}		_func		功能函数列表
 * @attribute	{Array}		_include	
 * @attribute	{Array}		_echo		
 * @attribute	{Array}		_text		
 * @attribute	{Array}		_script		
 * @attribute	{Array}		_sentence	
 */
class Functmpl {
	/**
	 * 构造函数
	 * @param  {Functmpl} parent 父模板
	 */
	constructor (parent) {
		this._status = 'new';
		this._filename = '';
		this._template = '';
		this._path = '';
		if (parent && parent instanceof Functmpl) {
			this._parent = parent;
			this._func = parent._func;
			this._include = parent._include;
			this._echo = parent._echo;
			this._text = parent._text;
			this._path = parent._path;
			this._script = parent._script;
			this._sentence = parent._sentence;
		} else {
			this._parent = null;
			this._func = [];
			this._include = [];
			this._echo = [];
			this._text = [];
			this._script = [];
			this._sentence = [];
			if (parent && typeof parent.path === "string") {
				this._path = parent.path;
			}
		}
	}

	get functmpl() {
		return functmpl;
	}
	get useType() {
		return useType;
	}
	get symbol() {
		return symbol;
	}
	get scope() {
		return scope;
	}
	get script() {
		return script;
	}


	/**
	 * 设置文件名
	 * @param  {String} name 文件名
	 * @throw {Error} 如果设置失败
	 */
	set filename(name) {
		if(!(this._status === 'new' || this._status === 'error' || this._status === 'wait')) {
			throw new Error("File is Loading or template is parsing!");
		}
		this._filename = name;
	}
	/**
	 * 获取文件名
	 * @return {String} 文件名
	 */
	get filename() {
		return this._filename;
	}

	/**
	 * 获取当前状态
	 * @return {String} 状态
	 */
	get status() {
		return this._status;

	}

	/**
	 * 设置模板
	 * @param  {String} text 模板文本
	 * @throw {Error} 如果设置失败
	 */
	async setTemplate(text) {
		if(!(this._status === 'new' || this._status === 'error' || this._status === 'wait')) {
			throw new Error("File is Loading or template is parsing!");
		}
		try {
			this._template = parse(text);
			this._status = 'wait';
		} catch (e) {
			this._status = 'error';
			throw e;
		}
	}

	/**
	 * 加载模板文件
	 * @param  {String} filename 模板文件名
	 * @throw {Error} 如果设置或加载失败
	 */
	async loadFile(filename) {
		if(!(this._status === 'new' || this._status === 'error' || this._status === 'wait')) {
			throw new Error("File is Loading or template is parsing!");
		}
		this._status = 'loading';
		this._filename = filename;
		filename = joinPath(this._path, filename);
		let data;
		try {
			data = await getFile(filename);
			this._template = parse(data);
			this._status = 'wait';
		} catch (e) {
			this._status = 'error';
			throw e;
		}
		
	}

	/**
	 * 添加处理函数
	 * @param  {Function} func 中间件
	 * @param  {String | Symbol} type 处理内容
	 * @return {Undefined}      undefined
	 */
	use(func, funcType) {
		let funcs;
		//假定输入为数组
		if (func instanceof Array) {
			funcs = func;
		} else {
			funcs = [func];
		}
		//处理并过滤出普通函数
		funcs = funcs.map(f => {
			if (typeof f === 'function') {
				//普通函数
				return f;
			} else if (typeof f === 'object'){
				//对象
				let {type: funcType, func} = f;
				//功能函数判断
				if (typeof func !== 'function') {
					return ;
				}
				//类型判断
				if (typeof funcType === "string") {
					//字符串则转为正则表达式
					funcType = new RegExp('^' + funcType + '$');
				} else if (!(funcType instanceof RegExp || useTypeSet.has(funcType))) {
					//类型既不是字符串、正则表达式，也不是特殊类型，则当做普通函数处理
					return func;
				}
				//根据类型处理，并直接加入函数列表
				switch(funcType) {
					case useType.include:
						this._include.push(func);
						break;
					case useType.echo:
						this._echo.push(func);
						break;
					case useType.text:
						this._text.push(func);
						break;
					default:
						this._func.push({type: funcType, func});
						break;
				}
			}
		}).filter(f=>f);
		//已经无函数则返回
		if (funcs.length === 0) {
			return;
		}
		//根据类型获取默认列表
		//符号标示特殊的处理单元
		//字符串或正则表达式标示特定匹配的功能
		//其他标示任意的功能
		let list;
		switch(funcType) {
			case useType.include:
				list = this._include;
				break;
			case useType.echo:
				list = this._echo;
				break;
			case useType.text:
				list = this._text;
				break;
			default:
				list = this._func;
				if (typeof funcType === "string") {
					funcType = new RegExp('^' + funcType + '$');
				} else if (!(funcType instanceof RegExp)) {
					funcType = new RegExp();
				}
				funcs = funcs.map(func => ({func, type: funcType}));
		}
		funcs.forEach(f => list.push(f));
	}

	/**
	 * 解析
	 * @param  {...Object} param 传入的作用域或数值
	 * @return {String}          解析后文本
	 */
	async parse(...param) {
		const ftl = this;
		if (ftl._status !== 'wait') {
			return null;
		}
		ftl._status = 'parsing';
		//作用域父对象
		let s = [];
		//主作用域
		let scope;
		param.forEach(p => {
			if (Scope.is(p) && !scope) {
				return scope = p;
			}
			s.push(p);
		});
		scope = Scope(scope);
		s.forEach(v => {
			for(let k in v) {
				scope[Scope.create](k,v[k]);
			}
		});
		//创建执行时this
		const that = Object.create(ftl);
		//返回值
		let ret = "";
		//输出函数
		that.echo = t => {ret += t;};
		await that.parseList(that._template, scope);
		return ret;
	}
	
	/**
	 * 解析列表
	 * @param {Array} 列表
	 * @param {Scope} 作用域
	 */
	async parseList(list, scope) {
		//对列表中项目尽心逐个解析
		for(let i = 0, l = list.length; i < l; i++) {
			await this.parseNode(list[i], scope);
		}
	}
	
	/**
	 * 解析节点
	 * @param {Object} 节点信息
	 * @param {Scope} 作用域
	 */
	async parseNode(node, scope) {
		//根据节点类型进行解析
		switch (node.type) {
		case 'func':{
			//标签名称，标签值，标签属性，子节点列表，子标签
			let {name, value, attr, list, sub} = node;
			let param = {};
			//标签值
			value = await value.get(scope);
			//参数列表
			for (let k in attr) {
				param[k] = await attr[k].get(scope);
			}
			//子标签
			for (let i = 0, l = sub.length; i < l; i++) {
				let node = sub[i];
				//子标签名称，子标签值，子标签属性，子节点列表
				let {name, value, attr, list} = node;
				let param = {};
				//子标签值
				value = await value.get(scope);
				//子标签参数列表
				for (let k in attr) {
					param[k] = await attr[k].get(scope);
				}
				//更新子标签信息
				sub[i] = {name, value, param, list};
			}
			return handle.call(
				this,
				{name, value, param, list, sub},
				scope,
				this._func.filter(x=>x.type.test(name)).map(({func})=>func)
			);
		}
		case 'include':
			//引入文件的前提是模板为确定的一个文件
			if(!this._filename) {
				return ;
			}
			return handle.call(
				this,
				joinPath(this._filename,"../", await node.value.exec(scope)),
				scope,
				this._include,
				baseInclude
			);
		case 'echo':
			return handle.call(
				this,
				node.value,
				scope,
				this._echo,
				async (t, s) => this.echo(await t.exec(s))
			);
		case 'text':
			return handle.call(
				this,
				node.value,
				scope,
				this._text,
				async t => this.echo(t)
			);
		case 'script':
			return handle.call(
				this,
				node.value,
				scope,
				this._script,
				async (t, s) => t.exec(s)
			);
		case 'sentence':
			return handle.call(
				this,
				node.value,
				scope,
				this._sentence
			);
		}
	}
	/**
	 * 将列表重复执行
	 * @param  {Array} list                 列表
	 * @param  {Scope} scope                作用域
	 * @param  {Object} data                重复数据
	 * @param  {String} options.key         键保存的变量名
	 * @param  {String} options.value       至保存的变量名
	 * @param  {String} options.total       总数保存的变量名
	 * @param  {String} options.num         总数保存的变量名（过时的，推荐用total）
	 * @param  {Boolean} options.release    是否将值展开
	 * @param  {Boolean} options.noBreak    是否不处理break
	 * @param  {Boolean} options.noContinue 是否不处理continue
	 * @param  {Object} options.base        将展开的基本数据
	 */
	async repeat(list, scope, data, {key, value, total, num, release, noBreak, noContinue, base}) {
		//将要重复的项目列表
		let items = [];
		if (typeof data === "number") {
			//重复数据是数字，仅表示重复次数
			for (let i = 0; i < data; i++) {
				items.push({key: i});
			}
			value = release = false;
		} else if (Array.isArray(data)) {
			//重复数据是数组
			//键为序号，从0开始
			//值为对应内容
			data.forEach((value, key) => items.push({key, value}));
		} else if (data && typeof data === "object") {
			//重复数据是对象
			//键为对象的键
			//值为对象对应的内容
			for (let k in data) {
				items.push({key: k, value: data[k]});
			}
		} else {
			//否则直接返回
			return;
		}
		if (typeof value !== "string") {
			value = "";
		}
		if (typeof key !== "string") {
			key = "";
		}
		if (!(total && typeof total === "string")) {
			total = typeof num === "string" ? num : "";
		}
		//循环处理
		for(let i = 0, l = items.length; i < l; i++) {try {
			let item = items[i];
			//获得子作用区域
			let childScope = Scope(scope);
			//键、值、总数的变量
			if (key) {
				childScope[Scope.create](key, item.key);
			}
			if (value) {
				childScope[Scope.create](value, item.value);
			}
			if (total) {
				childScope[Scope.create](total, l);
			}
			//展开值
			if (release && item.value && typeof item.value === 'object') {
				item = item.value;
				for(let k in item) {
					childScope[Scope.create](k, item[k]);
				}
			}
			//基本数据
			if (typeof base === 'object') {
				for(let k in base) {
					childScope[Scope.create](k,base[k]);
				}
			}
			//解析列表
			await this.parseList(list, childScope);
		} catch(sign) {
			//如果有信号
			if (sign === symbol.BREAK) {
				//break信号处理
				if (noBreak) {
					throw sign;
				}
				return ;
			} else if (sign === symbol.CONTINUE) {
				//continue信号处理
				if (noContinue) {throw sign;}
			} else if (typeof sign === "object" && sign.type === symbol.BREAK) {
				//多层break信号处理
				if (noBreak) {
					throw sign;
				}
				if (!sign.number || sign.number <= 0) {
					return ;
				}
				sign.number--;
				if (sign.number <= 0) {
					throw symbol.BREAK;
				}
				return ;
			} else if (sign && sign.type === symbol.CONTINUE) {
				//多层continue信号处理
				if (noContinue) {
					throw sign;
				}
				if (sign.number > 0) {
					sign.number--;
					if (sign.number <= 0) {
						throw symbol.CONTINUE;
					}
					throw sign;
				}
			} else {
				//其他信号
				throw sign;
			}
		}}
	}
}

/**
 * 插入目录
 */
function joinPath (path, ...allname) {
	let name = allname.shift();
	path = path.replace(/([/\\]+)/g,'/').split('/');
	name = name.replace(/([/\\]+)/g,'/').split('/');
	if(!name[0]) {path = [];}
	while(name.length) {
		let p = name.shift();
		if (p === '..') {path.pop();} 
		else if (p !== '.') {path.push(p);}
	}
	path = path.join("/")
	return allname.length ? joinPath(path, ...allname) : path;
}

/**
 * 深度复制对象
 * @param Object 被复制的对象
 * @return Object 复制产生的对象
 */
function deepCopy (source) {
	let result;
	let type = typeof source;
	if (type !== 'object' || source === null) {
		result = source;
	} else if (source instanceof Array){
		result = [];
		for (let i = 0,l = source.length; i < l;i++) {
			result[i] = typeof source[i]==='object' ? deepCopy(source[i]) : source[i];
		}
	} else {
		result = {};
		for (let k in source) {
			result[k] = typeof source[k]==='object' ? deepCopy(source[k]) : source[k];
		}
	}
	return result; 
}


/**
 * 节点处理
 * parseNode中使用
 * @param  {Any}				obj		处理的数据
 * @param  {Scope}				scope	作用域
 * @param  {Function[]}			list	处理函数列表
 * @param  {Function | null}	base	默认处理函数
 */
async function handle(obj, scope, list, base) {
	for (let i = 0, l = list.length; i < l; i++) {
		if (next !== await list[i].call(this, obj, scope, next)) {
			return ;
		}
	}
	if (base) {
		return base.call(this, obj, scope, next);
	}
}
/**
 * 默认包含函数
 * @param  {String} filename 文件名
 */
async function baseInclude(filename) {
	let f = new Functmpl(this);
	try{
		await f.loadFile(filename);
		return this.echo(await f.parse(scope));
	} catch(e) {}
}
/**
 * 获取文件内容
 * @param {String} 文件名
 * @param {Function} 回调函数
 */
function getFile(fn) {
	return new Promise((a, b) => fs.readFile(fn, 'utf-8', (e, d)=>e ? b(e) : a(d)));
}


/**
 * 解析
 * @param String 要解析的文本
 * @return Object 解析后的数据
 */
function parse(text) {
	//位置: 主位置, 引入, 功能, 子功能, 功能结束符, 语句, 表达式
	let index = 0, include = 0, func = 0, subfunc = 0, end = 0, script = 0, sentence = 0;
	//根, 当前位置
	let root = {list:[], main:null, sub:[]}, current = root;
	root.main = root;
	do {
		//首先查找各起点位置
		if (include !== -1) {
			include = text.indexOf("<#", index);
		}
		if (func !== -1) {
			func = text.indexOf("<@", index);
		}
		if (subfunc !== -1) {
			subfunc = text.indexOf("<|", index);
		}
		if (end !== -1) {
			end = text.indexOf("</>", index);
		}
		if (script !== -1) {
			script = text.indexOf("<`", index);
		}
		if (sentence !== -1) {
			sentence = text.indexOf("<%", index);
		}
		//选中的类型, 新的位置
		let type = '', newindex = text.length;
		//找出最靠前的起点及类型
		if (include !== -1 && include < newindex) {
			newindex = include;
			type = 'include';
		}
		if (func !== -1 && func < newindex) {
			newindex = func;
			type = 'func';
		}
		if (subfunc !== -1 && subfunc < newindex) {
			newindex = subfunc;
			type = 'subfunc';
		}
		if (end !== -1 && end < newindex) {
			newindex = end;
			type = 'end';
		}
		if (script !== -1 && script < newindex) {
			newindex = script;
			type = 'script';
		}
		if (sentence !== -1 && sentence < newindex) {
			newindex = sentence;
			type = '%';
		}
		//将中间字符加入队列
		if (index < newindex) {
			current.list.push({type:"text", value:text.substring(index, newindex)});
		}
		index = newindex;
		switch(type) {
		case 'include':
		case 'func':
		case 'subfunc':
		case 'script':
		case '%':
			//没有数据则直接返回
			if(!text.substr(index + 2, 1)) {
				break;
			}
			//获取标签信息
			let taginfo = parseTag(text, index + 2, {'include':'/', 'func':'', 'subfunc':'', 'script':'`', '%':'%'}[type]);
			if (!taginfo) {
				//无信息表示数据无效
				current.list.push({type:"text",value:"<"});
				index++;
			} else if (type === 'include') {
				//包含文件
				index = taginfo.index;
				let tag = {type, value: Script(taginfo.value)};
				current.list.push(tag);
			} else if (type === '%') {
				//表达式
				//设置新下标
				index = taginfo.index;
				let tag = {type: null, value:null};
				//获取首字符，进行进一步类型判断
				let ch = taginfo.value[0];
				//输出
				if (ch === "=") {tag.type = 'echo'; tag.value = Script(taginfo.value.substr(1));}
				//脚本
				else {tag.type = 'script'; tag.value = Script(taginfo.value);}
				//加入列表
				current.list.push(tag);
			} else if (type === 'script') {
				//表达式
				//设置新下标
				index = taginfo.index;
				let tag = {type: null, value:null};
				//获取首字符，进行进一步类型判断
				let ch = taginfo.value[0];
				if (ch === "=") {
				//输出
					tag.type = 'echo';
					tag.value = Script(taginfo.value.substr(1));
				} else if (ch === "`") {
					//不解析脚本
					let v = taginfo.value, i = 1, j = v.length - 1;
					while(v[i] === '`') {i++;}
					while(v[j] === '`') {j--;}
					if (j <= i) {break;}
					tag.type = 'sentence';
					tag.value = Script(taginfo.value.substr(i, j + 1));
				} else {
					//脚本
					tag.type = 'script';
					tag.value = Script(taginfo.value);
				}
				//加入列表
				current.list.push(tag);
			} else if (type === 'func' || type === 'subfunc') {
				//功能, 子功能
				//标签解析
				let funcInfo = parseFunc(taginfo.value);
				if (!funcInfo) {
					//标签解析失败
					current.list.push({type:"text", value:"<"});
					index++;
				} else {
					index = taginfo.index;
					if (type === 'func') {
						//创建
						let tag = {
							type: 'func', parent:current, list: [],
							name: funcInfo.name, value: funcInfo.value, 
							attr: funcInfo.attr, 
							main:null, sub:[], 
						};
						tag.main = tag;
						current.list.push(tag);
						if(!taginfo.closed) {current = tag;}
					} else if (type === 'subfunc') {
						let tag = {
							list: [], parent:current.parent, 
							name: funcInfo.name, value: funcInfo.value, 
							attr: funcInfo.attr, main:current.main, 
						};
						current.main.sub.push(tag);
						delete current.main;
						delete current.parent;
						current = tag;
						if (taginfo.closed && current !== root) {
							let parent = current.parent;
							delete current.parent;
							delete current.main;
							current = parent;
						}
					}
				}
			} else {
				index = taginfo.index;
				let tag = {type: type, value: null};
				tag.value = Script(taginfo.value);
				current.list.push(tag);
			}
			break;
		case 'end':
			if (current !== root) {
				let parent = current.parent;
				delete current.parent;
				delete current.main;
				current = parent;
			}
			index += 3;
			break;
		}
	} while (subfunc !== -1 || func !== -1 || end !== -1 || include !== -1 || script !== -1 || sentence !== -1);
	return root.list;
}

function parseTag (text, begin, sign) {
	//位置: 主位置, 在字符串中, 引号, 代码, 反斜杠, 结束符
	let index = begin, instr = false, quote = 0, code = 0, slant = 0, end = 0;
	if (sign) { sign += ">";}
	else {sign = ">";}
	do {
		if (quote !== -1) {quote = text.indexOf("\"", index);}
		if (slant !== -1) {slant = text.indexOf("\\", index);}
		if (code !== -1) {code = text.indexOf("`", index);}
		if (end !== -1) {end = text.indexOf(sign, index);}
		//选中的类型, 新的位置
		let type = 0, newindex = text.length;
		if (quote !== -1 && quote < newindex) {newindex = quote; type = 'quote';}
		if (slant !== -1 && instr && slant < newindex) {newindex = slant; type = 'slant';}
		if (end !== -1 && !instr && end < newindex) {newindex = end; type = 'end';}
		if (code !== -1 && !instr && code < newindex) {newindex = code; type = 'code';}
		index = newindex + 1;
		switch(type) {
		case 'quote':
			instr = !instr;
			break;
		case 'slant':
			index++;
			break;
		case 'code':
			if (sign === "`>") {
				if (begin + 1 === index) {
					while(text[index] === "`") {index++;}
					break;
				}
				while(text[index] === "`" && index !== text.indexOf('`>', index)) {index++;}
				if (index !== text.indexOf(sign, index)) {return null;};
				end = index;
			} else {
				while(text[index] === "`") {index++;}
				index = text.indexOf("`", index);
				if (index === -1) {return null;}
				while(text[index] === "`") {index++;}
				break;
			}
		case 'end':
			if (sign === "`>" && begin + 1 === index) {break;}
			text = text.substring(begin, end);
			let closed = false;
			if (sign === '>' && text.substr(-1) === '/') {
				text = text.substr(0,text.length - 1);
				closed = true;
			}
			return {value:text,closed:closed,index:index + sign.length - 1};	
		}
	} while (end !== -1);
	return null;
}

function parseFunc (text) {

	//位置: 主位置, 属性位置, 在字符串中, 代码, 引号, 反斜杠, 空格, 制表符, 回车
	let index = 0, attrindex = 0, instr = false, code = 0, quote = 0, slant = 0, space = 0, tab = 0, enter = 0;
	//标签名, 值, 属性
	let name = '', value, attr = {};
	do {
		if (quote !== -1) {quote = text.indexOf("\"",index);}
		if (slant !== -1) {slant = text.indexOf("\\",index);}
		if (code !== -1) {code = text.indexOf("`",index);}
		if (space !== -1) {space = text.indexOf(" ",index);}
		if (tab !== -1) {tab = text.indexOf("	",index);}
		if (enter !== -1) {enter = text.indexOf("\n",index);}
		//选中的类型, 新的位置
		let type = 'space', newindex = text.length;
		if (quote !== -1 && quote < newindex) {newindex = quote; type = 'quote';}
		if (slant !== -1 && instr && slant < newindex) {newindex = slant; type = 'slant';}
		if (code !== -1 && !instr && code < newindex) {newindex = code; type = 'code';}
		if(!instr) {
			if (space !== -1 && space < newindex) { newindex = space; type = 'space';}
			if (tab !== -1 && tab < newindex) {newindex = tab; type = 'space';}
			if (enter !== -1 && enter < newindex) {newindex = enter; type = 'space';}
		}
		index = newindex + 1;
		switch(type) {
		case 'quote':
			instr = !instr;
			break;
		case 'slant':
			index++;
			break;
		case 'code':
			while(text[index] === "`") {index++};
			while(text[index] !== "`") {index++};
			newindex = index;
			while(text[index] === "`") {index++};
		case 'space':
			if (newindex === 0) {return null;}
			//获取单元数据
			let data = text.substring(attrindex, newindex);
			//去除空格，并设置下一属性起点
			while(text[index] === "\t" || text[index] === "\n"|| text[index] === " ") {index++};
			attrindex = index;
			//初步获取键值对
			let i = data.search("=");
			let k, v;
			if (i === -1) {k = data;}
			else {k = data.substring(0, i); v = data.substring(i + 1);}
			//处理键
			let o = true;
			if (!nameRegExp.test(k)) {o = false;}
			//处理值
			if (o && v) {
				if (v[0] ===	 '`') {
					//脚本
					let e = false;
					if (v[1] === '`') {e = true;}
					let i = 1;
					while(v[i] === "`") {i++};
					v = {
						value: Script(v.substring(i)), 
						type: e ? "sentence" : "run", 
						async get (scope){
							if (this.type === "sentence") {
								return this.value;	
							}
							return await this.value.exec(scope);
						}
					}
				} else {try{
					//特殊量
					v = {value: JSON.parse(v), async get () {return deepCopy(this.value)}}
				} catch(e) {
					//变量名
					if (v.search(/^[\u4E00-\u9FA5a-z_][\u4E00-\u9FA5a-z0-9_]*$/i) !== -1) {
						v = {value:v, type:"var", async get (scope) {return scope[this.value]}};
					} else {
						v = null;
					}
				}}
			}
			if (o & !v) {v = {async get () {return undefined;}};}
			//赋值处理
			if (!name) {if (o) {name = k; value = v;} else {return null;}} 
			else if (o) {attr[k] = v;}
			break;
		}
	} while (quote !== -1 || space !== -1 || slant !== -1);
	return {name, value, attr};
}

export default function functmpl(p) {
	return new Functmpl(p);
}
export {
	useType,
	symbol,
	scope,
	script,
	func,
}
functmpl.useType = useType;
functmpl.symbol = symbol;
functmpl.scope = scope;
functmpl.script = script;
functmpl.func = func;
